// 
//
//	File: Material.h
//
// Interface of real used Material.

#ifndef OY_MATERIAL_H
#define OY_MATERIAL_H

#include "AbstractMaterial.h"
#include "Script.h"
#include <d3d9.h>


// forwards
class MaterialProperty;


// Material
class CMaterial : public AbstractMaterial
{
public :
	CMaterial();			// creates a default material containing 1 empty pass
	CMaterial( char* MaterialStr );
	virtual ~CMaterial();

	// public interface
	virtual void Clear();
	virtual void LoadFromMaterialStr( char* str );
	virtual void Update( float elapsedTime );
	virtual void Clone( AbstractMaterial *pSrcMaterial );

	static D3DBLEND AlphaBlendFunc( const char* func, const Script & script );
	static D3DBLENDOP AlphaBlendOp( const char* op, const Script & script );
	static D3DCMPFUNC AlphaTestFunc( const char* func, const Script & script );
	static DWORD AlphaTestRef( const char* ref, const Script & script );
	static D3DSTENCILOP StencilOp( const char* op, const Script & script );
	static D3DCMPFUNC StencilFunc( const char* func, const Script & script );
	static D3DTEXTUREADDRESS TextureAddressingModes( const char* mode, const Script & script );
	static D3DTEXTUREFILTERTYPE TextureFilteringModes( const char* mode, const Script & script );
	static D3DTEXTUREOP GetTextureOp( const char* op, const Script & script );
	static DWORD GetTextureTa( const char* ta, const Script & script );
	//static ColorProperty::ColorOperation GetColorOperation( const char* op, const Script & script );

	static const int INIT_MATERIALPROPERTY_BEGIN_NUM = 32;
	static const int INIT_MATERIALPROPERTY_END_NUM = 32;
	static const int INIT_MATERIALPROPERTY_UPDATE_NUM = 2;

public:
	class Pass : public RenderPass
	{
	public :
		// ctor(s) & dtor
		Pass();
		virtual ~Pass();
		Pass * Clone();

		// public interface
		virtual void UpdateTexture(unsigned int texID, int unit);
		virtual void AddProperty( MaterialProperty * property );
		virtual void PreRender();
		virtual void PostRender();

		// public members
		OyArrayStack<MaterialProperty *> begin_;			// begin_ contains all the material properties
		OyArrayStack<MaterialProperty *> end_;				// end_ contains a subset of begin_
		OyArrayStack<MaterialProperty *> update_;			// update_ contains a subset of begin_
	};

private :
	// enumerates actions to take when a feature is not supported on the user's hardware
	enum EMaterialResult
	{
		MR_AllRight,	// everything's all right
		MR_SkipPass,	// skip the current render pass
		MR_Fallback		// fallback to the specified material
	};

	// private methods
	EMaterialResult SetupTexturing( const Script & script, Script::Section & scriptPass, Pass & pass );
	EMaterialResult SetupTexturStageState( const Script & script, Script::Section & scriptPass, Pass & pass );
	//EMaterialResult SetupColoring( const Script & script, Script::Section & scriptPass, Pass & pass );
	EMaterialResult SetupAlphaBlending( const Script & script, Script::Section & scriptPass, Pass & pass );
	EMaterialResult SetupAlphaTesting( const Script & script, Script::Section & scriptPass, Pass & pass );
	EMaterialResult SetupStencil( const Script & script, Script::Section & scriptPass, Pass & pass );
	EMaterialResult SetupVarious( const Script & script, Script::Section & scriptPass, Pass & pass );
	
	
	// no copy
	CMaterial( const CMaterial & );
	CMaterial & operator=( const CMaterial & );

	// friendship
	friend class MaterialProperty;
};


#endif